/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved.
 * secGear is licensed under the Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *     http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
 * PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#include <stdio.h>
#include <string.h>
#include "hotcalls_t.h"


#include "../include/common.h"
/* 
 * printf: 
 *   Invokes OCALL to display the enclave buffer to the terminal.
 */
void printf(const char *fmt, ...)
{
    char buf[BUFSIZ] = {'\0'};
    va_list ap;
    va_start(ap, fmt);
    vsnprintf(buf, BUFSIZ, fmt, ap);
    va_end(ap);
    ocall_print_string(buf);
}

void MyCustomEcall( void* data )
{
	int *counter = (int*)data;
	*counter += 1;
}

void EcallStartResponder( HotCall* hotEcall )
{
	void (*callbacks[1])(void*);
    callbacks[0] = MyCustomEcall;

    HotCallTable callTable;
    callTable.numEntries = 1;
    callTable.callbacks  = callbacks;

    HotCall_waitForCall( hotEcall, &callTable );
}

void EcallMeasureHotOcallsPerformance( uint64_t*     performanceCounters, 
                                       uint64_t      numRepeats,
                                       HotCall*      hotOcall )
{
	printf( "Running %s\n", __func__ );

	int         expectedData = 1;
	OcallParams *ocallParams = (OcallParams *)hotOcall->data;
	ocallParams->cyclesCount = &performanceCounters[ 0 ];

	const uint16_t requestedCallID = 0;
	HotCall_requestCall( hotOcall, requestedCallID, ocallParams ); //Setup startTime to current rdtscp()
	for( uint64_t i=0; i < numRepeats; ++i ) {
		ocallParams->cyclesCount = &performanceCounters[ i ];
		HotCall_requestCall( hotOcall, requestedCallID, ocallParams );

		expectedData++;
        if( ocallParams->counter != expectedData ){
            printf( "Error! ocallParams->counter is different than expected: %d != %d\n", ocallParams->counter, expectedData );
        }
	}
}

void EcallMeasureSDKOcallsPerformance( uint64_t*     performanceCounters, 
                                       uint64_t      numRepeats,
                                       OcallParams*  ocallParams )
{
	printf( "Running %s\n", __func__ );

	int         expectedData = 1;
	ocallParams->cyclesCount = &performanceCounters[ 0 ];

	const uint16_t requestedCallID = 0;
	MyCustomOcall( ocallParams ); //Setup startTime to current rdtscp()
	for( uint64_t i=0; i < numRepeats; ++i ) {
		ocallParams->cyclesCount = &performanceCounters[ i ];
		MyCustomOcall( ocallParams );

		expectedData++;
        if( ocallParams->counter != expectedData ){
            printf( "Error! ocallParams->counter is different than expected: %d != %d\n", ocallParams->counter, expectedData );
        }
	}
}

